//
//  GoogleMapDownloader.m
//  pa
//
//  Created by HaiJiao Chen on 12-8-25.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import <CoreFoundation/CoreFoundation.h>
#import <CommonCrypto/CommonDigest.h>
#import "GoogleMapDownloader.h"

@interface NSString (ENcode)
- (NSString*)URLEncodedString;
- (NSString*)URLEncodedStringWithCFStringEncoding:(CFStringEncoding)encoding;
@end

@implementation NSString (ENcode)
- (NSString*)URLEncodedString
{
	return [self URLEncodedStringWithCFStringEncoding:kCFStringEncodingUTF8];
}
- (NSString*)URLEncodedStringWithCFStringEncoding:(CFStringEncoding)encoding
{
	return [(NSString *) CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)[[self mutableCopy] autorelease], NULL, CFSTR("￼=,!$&'()*+;@?\n\"<>#\t :/"),encoding) autorelease];
}
@end


NSString* GoogleMapDownloaderNotification = @"GoogleMapDownloaderNotification";

static GoogleMapDownloader* GoogleMapDownloader_sharedInstance = nil;

@implementation GoogleMapDownloader

- (id)init
{
    self = [super init];
    if (self)
    {
        downloaders = [[NSMutableDictionary alloc] initWithCapacity:10];
        need_to_download = [[NSMutableArray alloc] initWithCapacity:10];
        
        //NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        diskCachePath = [[NSTemporaryDirectory() stringByAppendingPathComponent:@"ImageCache"] retain];
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath])
        {
            [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath
                                      withIntermediateDirectories:YES
                                                       attributes:nil
                                                            error:NULL];
        }
    }
    return self;
}

- (void)dealloc
{
    [need_to_download release];
    [downloaders release];
    [diskCachePath release];
    [super dealloc];
}

- (NSString *)cachePathForKey:(NSString *)key
{
    const char *str = [key UTF8String];
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), r);
    NSString *filename = [NSString stringWithFormat:@"_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
    
    return [diskCachePath stringByAppendingPathComponent:filename];
}

- (UIImage*)downloadMap:(NSString*)address
{
    if (address != nil)
    {
        NSString* makers = [NSString stringWithFormat:@"color:red|color:red|label:C|%@", address];
        makers = [makers URLEncodedString];
        NSString * url = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/staticmap?markers=%@&zoom=13&size=1000x1000&sensor=false", makers];
        UIImage *image = [[[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:address]] autorelease];
        if (image == nil)
        {
            if ([need_to_download count] == 0)
            {
                if ([downloaders valueForKey:address] == nil)
                {
                    NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithCapacity:10];
                    
                    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
                    [request setURL:[NSURL URLWithString:url]];
                    [request setTimeoutInterval:10];
                    [request setHTTPMethod:@"GET"];
                    
                    NSMutableData* data = [[NSMutableData alloc] initWithCapacity:100];
                    [dic setValue:data forKey:@"data"];
                    [data release];
                    
                    NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
                    [dic setValue:connection forKey:@"connection"];
                    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
                    [connection start];
                    [request release];
                    
                    [downloaders setValue:dic forKey:address];
                    [dic release];
                }
            }
            else
            {
                [need_to_download removeObject:address];
                [need_to_download addObject:address];
            }
        }
        return image;
    }
    return nil;
}

- (NSString*)getConnectionUrl:(NSURLConnection*)aConnection
{
    NSArray* allkeys = downloaders.allKeys;
    for (NSString* key in allkeys)
    {
        NSDictionary* temp = [downloaders objectForKey:key];
        if ([temp valueForKey:@"connection"] == aConnection)
        {
            return key;
        }
    }
    return nil;
}

- (NSMutableData*)getConnectionBuffer:(NSURLConnection*)aConnection
{
    NSArray* allkeys = downloaders.allKeys;
    for (NSString* key in allkeys)
    {
        NSDictionary* temp = [downloaders objectForKey:key];
        if ([temp valueForKey:@"connection"] == aConnection)
        {
            return [temp valueForKey:@"data"];
        }
    }
    return nil;
}

-(void)continueQueue
{
    if ([need_to_download count] > 0)
    {
        NSString* address = [[need_to_download objectAtIndex:0] retain];
        [need_to_download removeObjectAtIndex:0];
        [self downloadMap:address];
        [address release];
    }
}

#pragma mark NSURLConnection (delegate)

- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data
{
    [[self getConnectionBuffer:aConnection] appendData:data];
}

#pragma GCC diagnostic ignored "-Wundeclared-selector"
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
    NSData* data = [self getConnectionBuffer:aConnection];
    NSString* address = [self getConnectionUrl:aConnection];
    
    [data writeToFile:[self cachePathForKey:address] atomically:YES];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:GoogleMapDownloaderNotification object:address];
    
    NSDictionary* temp = [downloaders objectForKey:address];
    NSURLConnection* connection = [temp valueForKey:@"connection"];
    [connection cancel];
    [downloaders removeObjectForKey:address];
    
    [self continueQueue];
}

- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)error
{
    NSString* address = [self getConnectionUrl:aConnection];
    [downloaders removeObjectForKey:address];
    [self continueQueue];
}


+ (GoogleMapDownloader*)sharedInstance
{
    if (GoogleMapDownloader_sharedInstance == nil)
    {
        GoogleMapDownloader_sharedInstance = [[GoogleMapDownloader alloc] init];
    }
    return GoogleMapDownloader_sharedInstance;
}

@end
